package com.ego.member.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ego.common.constant.MemberConstant;
import com.ego.common.constant.SystemConstant;
import com.ego.common.exception.GlobalException;
import com.ego.common.to.member.MemberTo;
import com.ego.common.util.PageUtil;
import com.ego.common.vo.PageVo;
import com.ego.common.vo.WeeklyDataVo;
import com.ego.member.po.MemberReceiveAddress;
import com.ego.member.service.MemberReceiveAddressService;
import com.ego.member.vo.MemberLoginVo;
import com.ego.member.vo.MemberRegisterVo;
import com.ego.member.vo.MemberSearchVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.ego.member.dao.MemberDao;
import com.ego.member.po.Member;
import com.ego.member.service.MemberService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @program: ego
 * @description 会员对应实现类
 * @author KamTang
 * @date 2022-11-13 13:28:12
 */
@Service("memberService")
@Slf4j
public class MemberServiceImpl extends ServiceImpl<MemberDao, Member> implements MemberService {

    @Autowired
    private MemberReceiveAddressService memberReceiveAddressService;

    @Override
    public PageVo<Member> search(MemberSearchVo search) {
        LambdaQueryWrapper<Member> query = Wrappers.<Member>lambdaQuery()
                .like(StringUtils.isNotEmpty(search.getKeyword()), Member::getNickname, search.getKeyword())
                .or().like(StringUtils.isNotEmpty(search.getKeyword()), Member::getUsername, search.getKeyword())
                .or().like(StringUtils.isNotEmpty(search.getKeyword()), Member::getCity, search.getKeyword())
                .or().like(StringUtils.isNotEmpty(search.getKeyword()), Member::getJob, search.getKeyword())
                .or().like(StringUtils.isNotEmpty(search.getKeyword()), Member::getSign, search.getKeyword());
        Page<Member> page = baseMapper.selectPage(Page.of(search.getPageNum(), search.getPageSize()), query);
        return PageUtil.toPage(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void register(MemberRegisterVo register) {
        // 检查用户名和手机号是否唯一
        unique(register.getPhone(), register.getUsername());
        Member member = new Member();

        // 密码进行加密后保存
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String encodePassword = encoder.encode(register.getPassword());
        member.register(register, encodePassword);
        this.save(member);
    }

    @Override
    public Member login(MemberLoginVo login) {
        String account = login.getLoginAccount();
        String password = login.getPassword();
        Member member = this.baseMapper.selectOne(new QueryWrapper<Member>().eq("username", account)
                .or().eq("mobile", account));
        if (ObjectUtils.isNotEmpty(member)) {
            MemberReceiveAddress defaultReceiveAddress = getDefaultReceiveAddress(member.getId());
            if (ObjectUtils.isNotEmpty(defaultReceiveAddress)) {
                member.setDefaultReceiveAddress(defaultReceiveAddress.getDetailAddress());
            }
            String encodePassword = member.getPassword();
            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
            if (encoder.matches(password, encodePassword)) {
                return member;
            }
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Member oauth2Login(MemberTo socialMember) {
        // 登录和注册合并
        String uid = socialMember.getSocialUid();
        // 判断当前社交用户是否已经登录过系统
        Member member = this.baseMapper.selectOne(new QueryWrapper<Member>().eq("social_uid", uid));
        // 保存收货地址
        MemberReceiveAddress defaultReceiveAddress = getDefaultReceiveAddress(member.getId());
        if (ObjectUtils.isNotEmpty(defaultReceiveAddress)) {
            member.setDefaultReceiveAddress(defaultReceiveAddress.getDetailAddress());
        }
        if (ObjectUtils.isNotEmpty(member)) {
            // 这个用户已经注册过
            member.socialMerge(socialMember);
            this.baseMapper.updateById(member);
            // 注意！这里的用户信息不是最新，只是我们不需要用户的最新数据。

            return member;
        } else {
            // 没有查到当前社交用户的信息，就需要自动为其注册。
            Member regMember = Member.fromTo(socialMember);
            this.save(regMember);
            return regMember;
        }
    }

    @Override
    public Map<String, List<?>> getWeeklyRegisterData() {
        List<WeeklyDataVo> data = this.baseMapper.getWeeklyRegisterData();
        // 近期一周用户注册详细情况
        List<Integer> count = data.stream().map(WeeklyDataVo::getCount).collect(Collectors.toList());
        int total = 0;
        for (Integer i : count) {
            total += i;
        }
        // 获取周
        List<String> weekend = data.stream().map(WeeklyDataVo::getWeekend).collect(Collectors.toList());
        // 总注册用户人数
        List<Integer> regTimes = new ArrayList<>(Collections.singletonList(total));
        // 存放最后结果
        Map<String, List<?>> map = new HashMap<>(4);
        // 设置标题
        ArrayList<String> titles = new ArrayList<>();
        titles.add("用户注册数");
        map.put("xAbscissa", weekend);
        map.put("blueData", count);
        map.put("titles", titles);
        map.put("userTotal", regTimes);
        return map;
    }

    /**
     * 用户唯一性
     * @param phone 电话
     * @param username 用户名
     */
    private void unique(String phone, String username) throws GlobalException {
        Long countByUsername = this.baseMapper
                .selectCount(new QueryWrapper<Member>().eq("username", username));
        if (countByUsername > 0) {
            throw new GlobalException(SystemConstant.Status.USERNAME_ALWAYS_EXISTS.getMsg());
        }
        Long countByPhone = this.baseMapper
                .selectCount(new QueryWrapper<Member>().eq("mobile", phone));
        if (countByPhone > 0) {
            throw new GlobalException(SystemConstant.Status.PHONE_REGISTERED.getMsg());
        }
    }

    /**
     * 获取用户（会员）默认收货地址
     * @param memberId 用户（会员）id
     * @return to see MemberReceiveAddress
     * @see MemberReceiveAddress
     */
    public MemberReceiveAddress getDefaultReceiveAddress(Long memberId) {
        List<MemberReceiveAddress> allAddresses = memberReceiveAddressService.gets(memberId);
        if (!CollectionUtils.isEmpty(allAddresses)) {
            List<MemberReceiveAddress> addresses = allAddresses.stream().map(i -> {
                if (i.getDefaultStatus() == MemberConstant.DEFAULT_RECEIVE_ADDRESS.intValue()) {
                    return i;
                } else {
                    return null;
                }
            }).collect(Collectors.toList());
            return addresses.get(0);
        } else {
            return null;
        }
    }
}
